/******************************************************************************
 *
 * ngcap - network sniffer using raw sockets
 *
 * Author:        cr
 * E-mail:        cr.at.netgarage.org
 * WWW:           http://www.netgarage.org
 * Copyright (C): 2009 by cr
 *
 * This file is part of ngcap.
 *
 * ngcap is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ngcap is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ngcap.  If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************/

#include "packethandler.hpp"
#include <cstring>

int capturedPacket::packetcount=0;

void PacketHandler::receivePackets()
{
    char buffer[1518];
    unsigned char* data;
    ssize_t size=0;
    int failurecount=0;
    while (failurecount<10){
        try{
            size=rawsock.receive(buffer);
        } catch(SocketError& ex){
            ++failurecount;
            continue;
        }
        data=new unsigned char[size];
        memcpy(data,buffer,size);
        pthread_mutex_lock(&qmutex);
            packets.push(new Packet(data, size));
        pthread_mutex_unlock(&qmutex);
        pthread_mutex_lock(&cmutex);
            pthread_cond_signal(&notempty);
        pthread_mutex_unlock(&cmutex);
    }
    receiving=false;
}

void PacketHandler::handlePackets()
{
    Packet* p;
    capturedPacket cp;
    pthread_mutex_lock(&cmutex);
    while(receiving){
        while(packets.empty())
            pthread_cond_wait(&notempty, &cmutex);
        pthread_mutex_unlock(&cmutex);
        pthread_mutex_lock(&qmutex);
        p=packets.front();
        packets.pop();
        pthread_mutex_unlock(&qmutex);
        cp=analyzePacket(p);
        if(!cp.getDrop())
            cp.print();
        cp.clear();
        delete p;
    }
}

capturedPacket PacketHandler::analyzePacket(Packet* p)
{
    //Trace t("analyze Packet..");
    capturedPacket cp;
    unsigned char* data=p->getData();

    Frame* fp=new EthernetFrame(data);
    do {
        if(fp->matchFilter(filter)){
            cp.packet.push_back(fp);
            fp=fp->getNext();
        } else return cp;
    } while(fp!=0);
    cp.setDrop(false);
    return cp;
}

